<?php
/***********************************************************************
 * @package     IvanEngine
 * @subpackage  Framwork
 * @author      Ivan <ivanzx@msn.com>
 * @created     2010-05-30
 ***********************************************************************/
if(defined("IVANENGINE_FRAMEWORK_CINFIG"))
    die("Redefinition macro in :".__FILE__."(".__LINE__.")");
define("IVANENGINE_FRAMEWORK_CINFIG", true);

abstract class CConfig extends CSingleton
{
    const OT_ProjPath       = 'ProjPath';
    const OT_CachePath      = 'CachePath';
    const OT_PluginPath     = 'PluginPath';
    const OT_InPluginPath   = 'InternalPluginPath';
    const OT_ThemesPath     = 'ThemesPath';
    const OT_Language       = 'Language';
    const OT_ActivePlugins  = 'ActivePlugins';
    const OT_CurrentThemes  = 'CurrentThemes';
    const OT_RoutingClass   = 'RoutingClass';
    const OT_SecurePlugin   = 'SecurePlugin';
    const OT_SecureAction   = 'SecureAction';
    
    protected
        $m_options              = null,
        $m_config               = null;
        
    static public $configClass  = null;
    static protected $m_this    = null;
    
    public function __construct() 
    {
        parent::__construct();
        CLog::Get()->Level(CLog::LEVEL_WARING);
        $this->m_options    = new CMap();
        $this->m_config     = new CXml();
        $this->AddOption(self::OT_InPluginPath, 
            CFileHelper::CorrectPath(M_ENGINE_PATH.'..'.M_DS.'Plugins'));
        $this->Config();
    }
    
    public function __destruct()
    {
        unset($this->m_options);
        parent::__destruct();
    }
    
    static public function Get()
    {
        if( self::$configClass == null )
        {
            throw new CExceptionInvalidArgument(
                'CConfig::$configClass is null, You must set it in you config class.');
        }
        if( self::$m_this == null )
        {
            parent::StartSingleton();
            self::$m_this = new self::$configClass();
            parent::EndSingleton();
        }
        return self::$m_this;
    }
    
    static public function Option($key, $val = null)
    {
        return CConfig::Get()->_Option($key, $val);
    }
    
    abstract protected function Config();
    
    public function Initialize()
    {
        CCacheManager::Get()->AddCacheFile(
            M_ENGINE_PATH.'Config'.M_DS.'Config.xml', 
            new CCacheCallback('LoadConfig', $this),
            CCacheManager::Get()->GetCacheFilePath(M_DS.'Config'.M_DS.'Config.dat'));
    }
    
    public function _Option($key, $val = null)
    {
        if( $val == null ){
            return $this->m_options->Get($key);
        }else{
            $this->m_options->Set($key, $val);
        }
    }
    
    public function AddOption($key, $val)
    {
        $this->m_options->Add($key, $val);
    }
    
    public function LoadConfig($isGenerate, $origin, $cache, $standby)
    {
        if( $isGenerate ){
            $this->m_config->Load($origin);
            $content    = $this->m_config->serialize();
            CFileHelper::Write($cache, $content);
        }else{
            $content = CFileHelper::Read($cache);
            $this->m_config->unserialize($content);
        }
        $this->_LoadConfig();
    }
    
    private function _LoadConfig()
    {
        $xmlRootNode        = $this->m_config->GetRoot();
        
        foreach( $xmlRootNode as $key => $value )
        {
            if( $this->m_options->Get($key) === null)
            {
                if( $value->GetAttributeCount() > 0 ){
                    $this->m_options->Add($key, $value);
                }else{
                    $this->m_options->Add($key, $value->GetContent());
                }
            }
        }
        
        $activePluginsNode  = $xmlRootNode->GetChild('ActivePlugins');
        $activePluginsArray = explode(',', $activePluginsNode->GetContent());
        $activePluginVector = new CVector();
        foreach( $activePluginsArray as $plugin ){
            $activePluginVector->Add($plugin);
        }
        $this->m_options->Set(self::OT_ActivePlugins, $activePluginVector);
        
        // secure option
        $secureNode = CConfig::Option('Secure');
        if(!$secureNode instanceof CXmlNode ){
            throw new CExceptionInvalidArgument(
                'Secure option has error in config.xml');
        }
        $securePlugin = $secureNode->GetAttribute('plugin');
        $secureAction = $secureNode->GetAttribute('action');
        if( !$securePlugin || $securePlugin == '' || 
            !$secureAction || $secureAction == '')
        {
            throw new CExceptionInvalidArgument(
                'Secure option has error in config.xml');
        }
        
        $this->m_options->Add(self::OT_SecurePlugin, $securePlugin);
        $this->m_options->Add(self::OT_SecureAction, $secureAction);
    }
    
    public function & GetXml()
    {
        return $this->m_config;
    }
    
    public function Save()
    {
        $this->m_config->Save();
    }
}
?>
